package cn.com.utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import cn.com.consts.MsgCd;
import cn.com.spring.annotation.Bean;

/**
 * 线程池实用程序
 *
 * @author LiuGuodong
 * @date 2024/01/26
 */
public class ThreadPoolUtils {

    private static ThreadPoolExecutor executorService;

    private final static Map<String, ThreadPoolExecutor> STRING_EXECUTOR_SERVICE_MAP = new ConcurrentHashMap<>();

    static {
        executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(50);
        STRING_EXECUTOR_SERVICE_MAP.put("default", executorService);
        //todo 待优化为 切面
        Class<ThreadPoolUtils> utilsClass = ThreadPoolUtils.class;
        Arrays.stream(utilsClass.getMethods())
                .filter(method -> method.isAnnotationPresent(Bean.class))
                .forEach(method -> {
                    Bean annotation = method.getAnnotation(Bean.class);
                    String name = StringUtil.isBlank(annotation.name()) ? method.getName() : annotation.name();
                    STRING_EXECUTOR_SERVICE_MAP.put(name, executeMethod(method));
                });
    }

    /**
     * execute方法
     *
     * @param method 方法
     * @return {@link ThreadPoolExecutor}
     */
    private static ThreadPoolExecutor executeMethod(Method method) {
        try {
            return (ThreadPoolExecutor) method.invoke(null);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

    @Bean
    private static ThreadPoolExecutor tagPoolExecutor() {
        return new ThreadPoolExecutor(30, 50, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2000), new ThreadPoolExecutor.CallerRunsPolicy());
    }

    @Bean
    public static ThreadPoolExecutor threadPoolTaskExecutor() {
        return new ThreadPoolExecutor(30, 50, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2000), new ThreadPoolExecutor.CallerRunsPolicy());
    }

    @Bean
    public static ThreadPoolExecutor myThreadPool() {
        return new ThreadPoolExecutor(30, 50, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2000), new ThreadPoolExecutor.CallerRunsPolicy());

    }

    @Bean
    public static ThreadPoolExecutor myThreadPoolTaskExecutor() {
        return new ThreadPoolExecutor(30, 50, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2000), new ThreadPoolExecutor.CallerRunsPolicy());
    }

    /**
     * 切换线程池impl
     *
     * @param name 名称
     */
    public static void switchThreadPoolImpl(String name) {
        executorService = STRING_EXECUTOR_SERVICE_MAP.getOrDefault(name, executorService);
    }

    /**
     * 提交任务
     *
     * @param task 任务
     * @return {@link Object}
     */
    public static <T> Object submitTask(Callable<T> task) {
        if (executorService == null || executorService.isShutdown()) {
            throw new IllegalStateException(WebUtil.getMessage(MsgCd.ERR_MSG_BSS_104396728));
        }
        Future<T> submit = executorService.submit(task);
        try {
            return submit.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 提交任务
     *
     * @param task 任务
     * @param name 线程池名称
     * @return {@link Object}
     */
    public static <T> Object submitTask(Callable<T> task, String name) {
        switchThreadPoolImpl(name);
        return submitTask(task);
    }

    /**
     * 提交任务
     *
     * @param task 任务
     * @param name 线程池名称
     */
    public static void submitTask(Runnable task, String name) {
        switchThreadPoolImpl(name);
        submitTask(task);
    }

    /**
     * 提交任务
     *
     * @param task 任务
     */
    public static void submitTask(Runnable task) {
        if (executorService == null) {
            throw new IllegalStateException(WebUtil.getMessage(MsgCd.ERR_MSG_BSS_1455365881));
        }
        (executorService).execute(task);
        //保证线程池不修改始终为默认
        executorService = STRING_EXECUTOR_SERVICE_MAP.get("default");
    }
}
